home *** CD-ROM | disk | FTP | other *** search
- /
- / Copyright (C) 1990-1992 Mark Adler, Richard B. Wales, Jean-loup Gailly,
- / Kai Uwe Rommel and Igor Mandrichenko.
- / Permission is granted to any individual or institution to use, copy, or
- / redistribute this software so long as all of the original files are included
- / unmodified, that it is not sold for profit, and that this copyright notice
- / is retained.
- /
- / match.s by Jean-loup Gailly. Translated to 32 bit code by Kai Uwe Rommel.
-
- / match.s, optimized version of longest_match() in deflate.c
- / This version is for 386 Unix or OS/2 in 32 bit mode.
- / Warning: it uses the AT&T syntax: mov source,dest
- / This file is only optional. If you want to force the C version,
- / add -DNO_ASM to CFLAGS in makefile and remove match.o from OBJI).
- / If you have reduced WSIZE in zip.h, then change its value below.
- / This version assumes static allocation of the arrays (-DDYN_ALLOC not used).
-
- .file "match.s"
-
- #if defined(__GO32__) && defined(unix)
- # undef unix
- #endif
-
- #ifdef unix
- # define _prev prev
- # define _window window
- # define _match_start match_start
- # define _prev_length prev_length
- # define _good_match good_match
- # define _strstart strstart
- # define _max_chain_length max_chain_length
-
- # define _match_init match_init
- # define _longest_match longest_match
- #endif
-
- #define MAX_MATCH 258
- #define MAX_MATCH2 128 /* MAX_MATCH/2-1 */
- #define MIN_MATCH 3
- #define WSIZE 32768
- #define MAX_DIST WSIZE - MAX_MATCH - MIN_MATCH - 1
-
- .globl _match_init
- .globl _longest_match
-
- .text
-
- _match_init:
- ret
-
- / -----------------------------------------------------------------------
- / Set match_start to the longest match starting at the given string and
- / return its length. Matches shorter or equal to prev_length are discarded,
- / in which case the result is equal to prev_length and match_start is
- / garbage.
- / IN assertions: cur_match is the head of the hash chain for the current
- / string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
-
- _longest_match: /* int longest_match(cur_match) */
-
- #define cur_match 20(%esp)
- / return address / esp+16
- push %ebp / esp+12
- push %edi / esp+8
- push %esi / esp+4
- push %ebx / esp
-
- / match equ esi
- / scan equ edi
- / chain_length equ ebp
- / best_len equ ebx
- / limit equ edx
-
- mov cur_match,%esi
- mov _max_chain_length,%ebp / chain_length = max_chain_length
- mov _strstart,%edi
- mov %edi,%edx
- sub $ MAX_DIST,%edx / limit = strstart-MAX_DIST
- jae limit_ok
- sub %edx,%edx / limit = NIL
- limit_ok:
- add $_window+2,%edi / edi = offset(window + strstart + 2)
- mov _prev_length,%ebx / best_len = prev_length
- movw -3(%ebx,%edi),%ax / ax = scan[best_len-1..best_len]
- movw -2(%edi),%cx / cx = scan[0..1]
- cmp _good_match,%ebx / do we have a good match already?
- jb do_scan
- shr $2,%ebp / chain_length >>= 2
- jmp do_scan
-
- .align 4
- long_loop:
- / at this point, edi == scan+2, esi == cur_match
- movw -3(%ebx,%edi),%ax / ax = scan[best_len-1..best_len]
- movw -2(%edi),%cx / cx = scan[0..1]
- short_loop:
- dec %ebp / --chain_length
- jz the_end
- / at this point, di == scan+2, si == cur_match,
- / ax = scan[best_len-1..best_len] and cx = scan[0..1]
- and $ WSIZE-1, %esi
- movw _prev(%esi,%esi),%si / cur_match = prev[cur_match]
- / top word of esi is still 0
- cmp %edx,%esi / cur_match <= limit ?
- jbe the_end
- do_scan:
- cmpw _window-1(%ebx,%esi),%ax /check match at best_len-1
- jne short_loop
- cmpw _window(%esi),%cx / check min_match_length match
- jne short_loop
-
- lea _window+2(%esi),%esi / si = match
- mov %edi,%eax / ax = scan+2
- mov $ MAX_MATCH2,%ecx / scan for at most MAX_MATCH bytes
- #ifdef unix
- repz; cmpsw / loop until mismatch
- #else
- repe; cmpsw
- #endif
- je maxmatch / match of length MAX_MATCH?
- mismatch:
- movb -2(%edi),%cl / mismatch on first or second byte?
- subb -2(%esi),%cl / cl = 0 if first bytes equal
- xchg %edi,%eax / edi = scan+2, eax = end of scan
- sub %edi,%eax / eax = len
- sub %eax,%esi / esi = cur_match + 2 + offset(window)
- sub $_window+2,%esi / esi = cur_match
- subb $1,%cl / set carry if cl == 0 (cannot use DEC)
- adc $0,%eax / eax = carry ? len+1 : len
- cmp %ebx,%eax / len > best_len ?
- jle long_loop
- mov %esi,_match_start / match_start = cur_match
- mov %eax,%ebx / ebx = best_len = len
- cmp $ MAX_MATCH,%eax / len >= MAX_MATCH ?
- jl long_loop
- the_end:
- mov %ebx,%eax / result = eax = best_len
- pop %ebx
- pop %esi
- pop %edi
- pop %ebp
- ret
- maxmatch:
- cmpsb
- jmp mismatch
-